package com.breeze.components.core.util.web;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ContentCachingRequestWrapper;

/**
 * @author breeze
 */
@Slf4j
public class RequestContextUtil {

  public static final String UNKNOWN_IP = "unknown-ip";
  public static final String UNKNOWN_URL = "unknown-url";
  public static final String URL_X_AES_KEY = "XX-KEY";

  public static String getClientIp() {
    return getRequest().map(JakartaServletUtil::getClientIP).orElse(UNKNOWN_IP);
  }

  public static String getRequestUrl() {
    return getRequest().map(HttpServletRequest::getRequestURI).orElse(UNKNOWN_URL);
  }

  public static Optional<HttpServletRequest> getRequest() {
    return Optional.ofNullable(
            (ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
        .map(ServletRequestAttributes::getRequest);
  }

  private static Optional<HttpServletResponse> getResponse() {
    return Optional.ofNullable(
            (ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
        .map(ServletRequestAttributes::getResponse);
  }

  public static String getArgs() {
    return getRequest()
        .map(
            s ->
                String.format(
                    "{\"param\":\"%s\",\"body\":\"%s\"}",
                    JSON.toJSONString(s.getParameterMap()), readBody(s)))
        .orElse(StrUtil.EMPTY);
  }

  private static Object readBody(HttpServletRequest s) {
    try {
      if (s instanceof ContentCachingRequestWrapper wrapper) {
        return new String(wrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
      }
      return IoUtil.read(s.getInputStream(), StandardCharsets.UTF_8);
    } catch (Exception e) {
      log.error("异常", e);
    }
    return StrUtil.EMPTY;
  }

  public static String getRequestHead() {
    return getRequest()
        .map(
            s -> {
              Enumeration<String> headerNames = s.getHeaderNames();
              HashMap<Object, Object> hashMap = new HashMap<>();
              while (headerNames.hasMoreElements()) {
                String key = headerNames.nextElement();
                hashMap.put(key, s.getHeader(key));
              }
              return hashMap.toString();
            })
        .orElse(StrUtil.EMPTY);
  }

  public static String getHeader(String headerLangKey) {
    return JakartaServletUtil.getHeader(
        Objects.requireNonNull(getRequest().orElse(null)), headerLangKey, StandardCharsets.UTF_8);
  }

  public static void addCookie(String key, String value) {
    getResponse()
        .ifPresent(
            s -> {
              s.addCookie(new Cookie(key, value));
            });
  }

  public static String getCookie(String key) {
    return getRequest()
        .flatMap(
            s ->
                Arrays.stream(Optional.ofNullable(s.getCookies()).orElse(new Cookie[0]))
                    .filter(Objects::nonNull)
                    .filter(inner -> Objects.equals(inner.getName(), key))
                    .findFirst()
                    .map(Cookie::getValue))
        .orElse(null);
  }
}
